package com.zb.kc.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Sets;
import com.zb.kc.commonutils.ExceptionUtil;
import com.zb.kc.entity.EduSubject;
import com.zb.kc.dao.EduSubjectDao;
import com.zb.kc.entity.excel.SubjectData;
import com.zb.kc.listener.SubjectExcelListener;
import com.zb.kc.service.IEduSubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

/**
 * <p>
 * 课程科目 服务实现类
 * </p>
 *
 * @author wanggen
 * @since 2020-04-09
 */
@Service
@Slf4j
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectDao, EduSubject> implements IEduSubjectService {

    @Override
    public void saveSubject(MultipartFile file, IEduSubjectService subjectService) {
        try {
            InputStream in = file.getInputStream();
            // 调用方法进行读取
            EasyExcel.read(in, SubjectData.class, new SubjectExcelListener(subjectService)).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
            log.info(ExceptionUtil.getMessage(e));
        }
    }

    @Override
    public List<EduSubject> getAllSubjectTree() {
        // 顶级分类的结合
        List<EduSubject> topList = baseMapper.selectList(new QueryWrapper<EduSubject>().eq("parent_id", "0"));
        // 非顶级分类的集合，其他所有分类
        List<EduSubject> otherList = baseMapper.selectList(new QueryWrapper<EduSubject>().ne("parent_id", "0"));
        if (ObjectUtil.isNotNull(otherList)) {
            // 声明一个set，用来保存已经遍历过的otherList中的节点,初始化大小就为子节点的数量
            Set<String> sets = Sets.newHashSetWithExpectedSize(otherList.size());
            // 遍历每一个顶级分类，给每个顶级分类构建子分类树
            topList.forEach(c -> getChild(c, otherList, sets));
        }
        return topList;
    }

    @Override
    public List<EduSubject> list2(String id) {
        if (StringUtils.isEmpty(id)) {
            return baseMapper.selectList(new QueryWrapper<EduSubject>().eq("parent_id", "0"));
        }
        return baseMapper.selectList(new QueryWrapper<EduSubject>().eq("parent_id", id));
    }

    /**
     * 总结递归思想:
     * 每个节点都需要找到自己的子节点，添加到childSubs中
     * 找到后将所有的子节点赋值给自己的childSubs
     *
     * @param sub
     * @param otherList
     * @param sets
     */
    private void getChild(EduSubject sub, List<EduSubject> otherList, Set<String> sets) {
        List<EduSubject> childSubs = new LinkedList<>();
        otherList.stream()
                .filter(c -> !sets.contains(sub.getId())) // 先过滤掉已经处理过的节点
                .filter(c -> c.getParentId().equals(sub.getId())) // 获取到了sub的所有子节点
                // 每个子节点都需要getChild
                .forEach(c -> {
                    // 在getChild前，可以先把自己排除掉，不用跟已经处理过的节点比较了
                    sets.add(c.getId());
                    // 递归的去给当前节点设置子节点
                    getChild(c, otherList, sets);
                    // 到达栈底，添加到当前的子节点中，然后依次的出栈返回
                    childSubs.add(c);
                });
        sub.setchildSubs(childSubs);
    }


}
